home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Util / Cag / cag.c next >
Encoding:
C/C++ Source or Header  |  1994-12-22  |  9.2 KB  |  520 lines

  1.  
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6.  
  7. struct node
  8. {
  9.     char name[32];
  10.     char title[32];
  11.     char body[256];
  12. };
  13.  
  14. struct cmd
  15. {
  16.     char nodes[40];
  17.     char name[32];
  18.     char args[80];
  19.     char text[256];
  20. };
  21.  
  22. struct desc
  23. {
  24.     char cmds[40];
  25.     int begin;
  26.     int len;
  27. };
  28.  
  29. char header[1024];
  30.  
  31. #define MAXNODES    50
  32. #define MAXCMDS     500
  33. #define MAXDESCS    100
  34.  
  35. struct node * node;
  36. struct cmd * cmd;
  37. struct desc * desc;
  38.  
  39. struct cmd * cmdtable[MAXCMDS];
  40.  
  41. int nnodes, ncmds, ndescs, lineno;
  42.  
  43. int cmp_nodes (const struct node * n1, const struct node * n2)
  44. {
  45.     return (strcmp (n1->title, n2->title));
  46. }
  47.  
  48. int cmp_cmds (const struct cmd * c1, const struct cmd * c2)
  49. {
  50.     return (strcmp (c1->name, c2->name));
  51. }
  52.  
  53. int cmp_cmdtable (const struct cmd ** c1, const struct cmd ** c2)
  54. {
  55.     return (strcmp ((*c1)->name, (*c2)->name));
  56. }
  57.  
  58. void add_node (char * line)
  59. {
  60.     char * name, * longname;
  61.  
  62.     if (nnodes >= MAXNODES) {
  63.     fprintf (stderr, "too many nodes!\n", __LINE__);
  64.     exit (10);
  65.     }
  66.  
  67.     line += 5;
  68.     while (isspace (*line)) line ++;
  69.  
  70.     name = strtok (line, "\t ");
  71.     longname = strtok (NULL, "\n");
  72.  
  73.     strcpy (node[nnodes].name, name);
  74.     strcpy (node[nnodes].title, longname);
  75.     node[nnodes].body[0] = 0;
  76.  
  77.     nnodes ++;
  78. } /* add_node */
  79.  
  80.  
  81. void add_cmd (char * line)
  82. {
  83.     char * nodes, * name, * args;
  84.     int t;
  85.  
  86.     if (ncmds >= MAXCMDS) {
  87.     fprintf (stderr, "too many cmds!\n", __LINE__);
  88.     exit (10);
  89.     }
  90.  
  91.     line += 4;
  92.     while (isspace (*line)) line ++;
  93.     if (!*line)
  94.     {
  95.     fprintf (stderr, "#cmd: unexpected EOL in line %d (%d)\n", lineno, __LINE__);
  96.     exit (10);
  97.     }
  98.  
  99.     nodes = line;
  100.     while (!isspace (*line) && *line) line ++;
  101.  
  102.     if (!*line)
  103.     {
  104.     fprintf (stderr, "#cmd: unexpected EOL in line %d (%d)\n", lineno, __LINE__);
  105.     exit (10);
  106.     }
  107.  
  108.     *line = 0;
  109.     line ++;
  110.  
  111.     while (isspace (*line)) line ++;
  112.     if (!*line)
  113.     {
  114.     fprintf (stderr, "#cmd: unexpected EOL in line %d (%d)\n", lineno, __LINE__);
  115.     exit (10);
  116.     }
  117.  
  118.     name = line;
  119.     while (!isspace (*line) && *line) line ++;
  120.  
  121.     if (!*line)
  122.     {
  123.     fprintf (stderr, "#cmd: unexpected EOL in line %d (%d)\n", lineno, __LINE__);
  124.     exit (10);
  125.     }
  126.  
  127.     *line = 0;
  128.     line ++;
  129.  
  130.     while (isspace (*line) && *line) line ++;
  131.     if (!*line)
  132.     {
  133.     fprintf (stderr, "#cmd: unexpected EOL in line %d (%d)\n", lineno, __LINE__);
  134.     exit (10);
  135.     }
  136.  
  137.     if (*line != '-')
  138.     {
  139.     args = line;
  140.  
  141.     while (*line)
  142.     {
  143.         if (isspace(*line) && line[1] == '-')
  144.         break;
  145.  
  146.         line ++;
  147.     }
  148.  
  149.     if (!*line)
  150.     {
  151.         fprintf (stderr, "#cmd: unexpected EOL in line %d (%d)\n", lineno, __LINE__);
  152.         exit (10);
  153.     }
  154.  
  155.     *line = 0;
  156.  
  157.     for (t=strlen(args)-1; t>=0; t--)
  158.         if (!isspace (args[t]))
  159.         break;
  160.  
  161.     args[t+1] = 0;
  162.     line += 2;
  163.     }
  164.     else
  165.     {
  166.     args = line;
  167.     *line = 0;
  168.     line ++;
  169.     }
  170.  
  171.     while (isspace (*line)) line ++;
  172.     if (!*line)
  173.     {
  174.     fprintf (stderr, "#cmd: unexpected EOL in line %d (%d)\n", lineno, __LINE__);
  175.     exit (10);
  176.     }
  177.  
  178.     strcpy (cmd[ncmds].nodes, nodes);
  179.     strcpy (cmd[ncmds].name, name);
  180.     strcpy (cmd[ncmds].args, args);
  181.     strcpy (cmd[ncmds].text, line);
  182.  
  183.     ncmds ++;
  184. } /* add_node */
  185.  
  186. void add_desc (char * line, FILE * fh)
  187. {
  188.     int len = strlen (line);
  189.  
  190.     line[len-1] = 0;
  191.  
  192.     if (ndescs >= MAXNODES) {
  193.     fprintf (stderr, "too many nodes!\n", __LINE__);
  194.     exit (10);
  195.     }
  196.  
  197.     line += 5;
  198.     while (isspace (*line)) line ++;
  199.  
  200.     strcpy (desc[ndescs].cmds, line);
  201.     desc[ndescs].begin = ftell (fh);
  202.  
  203.     if (ndescs)
  204.     desc[ndescs-1].len = desc[ndescs].begin - len - desc[ndescs-1].begin;
  205.  
  206.     ndescs ++;
  207. } /* add_desc */
  208.  
  209. int isinlist (char * elem, char * list)
  210. {
  211.     char * pos;
  212.     int len;
  213.  
  214.     pos = strstr (list, elem);
  215.     len = strlen (elem);
  216.  
  217.     /* is inside a list, if it is the first word or the last one or
  218.        delimited by ',' */
  219.     return (pos && (pos == list || pos[-1] == ',') && !isalpha(pos[len]));
  220. } /* isinlist */
  221.  
  222. char fmt_buf[100];
  223. #define MAXWIDTH 78
  224. #define INDENT 20
  225.  
  226. void fmt_cmd (FILE * out, struct cmd * cmd)
  227. {
  228.     int t, len, i;
  229.     char * last_space, * curr, * text;
  230.  
  231.     for (t=0; t<ndescs; t++)
  232.     if (isinlist (cmd->name, desc[t].cmds))
  233.         break;
  234.  
  235.     if (t != ndescs) /* found */
  236.     {
  237.     fprintf (out, "@{\" %s \" LINK \"desc%d\"}", cmd->name, t);
  238.     len = strlen (cmd->name)+3;
  239.  
  240.     if (cmd->args[0])
  241.     {
  242.         fprintf (out, " @{B}%s@{UB}", cmd->args);
  243.         len += strlen (cmd->args)+1;
  244.     }
  245.     }
  246.     else
  247.     {
  248.     fprintf (out, "@{B}%s", cmd->name);
  249.     len = strlen (cmd->name);
  250.  
  251.     if (cmd->args[0])
  252.     {
  253.         fprintf (out, " %s", cmd->args);
  254.         len += strlen (cmd->args)+1;
  255.     }
  256.  
  257.     fprintf (out, "@{UB}");
  258.     }
  259.  
  260.     if (len >= INDENT)
  261.     {
  262.     fputc (' ', out);
  263.     len ++;
  264.     }
  265.     else while (len < INDENT)
  266.     {
  267.     fputc (' ', out);
  268.     len ++;
  269.     }
  270.  
  271.     last_space = NULL;
  272.     curr = fmt_buf;
  273.     text = cmd->text;
  274.  
  275.     while (*text)
  276.     {
  277.     if (len > MAXWIDTH)
  278.     {
  279.         *curr = 0;
  280.  
  281.         if (!last_space)
  282.         last_space = curr;
  283.         else
  284.         last_space[-1] = 0;
  285.  
  286.         fprintf (out, "%s\n", fmt_buf);
  287.  
  288.         strcpy (fmt_buf, last_space);
  289.  
  290.         for (len=0; len < INDENT; len++)
  291.         fputc (' ', out);
  292.  
  293.         last_space = NULL;
  294.  
  295.         i = strlen (fmt_buf);
  296.         curr = fmt_buf + i;
  297.         len += i;
  298.     }
  299.     else
  300.     {
  301. again:
  302.         *curr = *text ++;
  303.  
  304.         if (isspace (*curr))
  305.         last_space = curr+1;
  306.         else if (*curr == '@' && *text == '{')
  307.         {
  308.         curr ++;
  309.  
  310.         while (*text != '}')
  311.         {
  312.             *curr ++ = *text ++;
  313.         }
  314.  
  315.         goto again; /* copy } too */
  316.         }
  317.  
  318.         len ++;
  319.         curr ++;
  320.     }
  321.     }
  322.  
  323.     *curr = 0;
  324.  
  325.     fprintf (out, "%s", fmt_buf);
  326. } /* fmt_cmd */
  327.  
  328.  
  329. int main (int argc, char ** argv)
  330. {
  331.     FILE * in;
  332.     char puffer[1024];
  333.     char line[256];
  334.     int llen;
  335.     int state;
  336.     int t, i, j, nx;
  337.  
  338.     if (!(in = fopen (argv[1], "r")) ) {
  339.     fprintf (stderr, "file '%s' not open!\n", argv[1], __LINE__);
  340.     exit (10);
  341.     }
  342.  
  343.     if (!(node = malloc (sizeof (struct node) * MAXNODES)) ) {
  344.     fprintf (stderr, "no memory!\n", __LINE__);
  345.     exit (10);
  346.     }
  347.  
  348.     if (!(cmd = malloc (sizeof (struct cmd) * MAXCMDS)) ) {
  349.     fprintf (stderr, "no memory!\n", __LINE__);
  350.     exit (10);
  351.     }
  352.  
  353.     if (!(desc = malloc (sizeof (struct desc) * MAXDESCS)) ) {
  354.     fprintf (stderr, "no memory!\n", __LINE__);
  355.     exit (10);
  356.     }
  357.  
  358.     state = 0;
  359.  
  360.     *header = 0;
  361.     *puffer = 0;
  362.  
  363.     while (fgets (line, sizeof(line), in))
  364.     {
  365.     llen = strlen (line);
  366.     lineno ++;
  367.  
  368.     switch (state)
  369.     {
  370.     case 0: /* header */
  371.         if (strncmp ("#toc", line, 4))
  372.         strcat (header, line);
  373.         else
  374.         state = 1;
  375.  
  376.         break;
  377.  
  378.     case 1: /* parse #node */
  379.         if (!strncmp ("#node", line, 5))
  380.         {
  381.         add_node (line);
  382.         state = 2;
  383.         }
  384.  
  385.         break;
  386.  
  387.     case 2: /* parse node-body until next node or #cmd */
  388.         if (!strncmp ("#node", line, 5))
  389.         {
  390.         add_node (line);
  391.         state = 2;
  392.         }
  393.         else if (!strncmp ("#cmd", line, 4))
  394.         {
  395.         add_cmd (line);
  396.         state = 3;
  397.         }
  398.         else
  399.         strcat (node[nnodes-1].body, line);
  400.  
  401.         break;
  402.  
  403.     case 3: /* parse #cmd until #long */
  404.         if (!strncmp ("#cmd", line, 4))
  405.         {
  406.         add_cmd (line);
  407.         }
  408.         else if (!strncmp ("#long", line, 5))
  409.         {
  410.         add_desc (line, in);
  411.         state = 4;
  412.         }
  413.  
  414.         break;
  415.  
  416.     case 4: /* parse #long until EOF */
  417.         if (!strncmp ("#long", line, 5))
  418.         {
  419.         add_desc (line, in);
  420.         state = 4;
  421.         }
  422.  
  423.         break;
  424.     }
  425.     }
  426.  
  427.     if (ndescs)
  428.     desc[ndescs-1].len = ftell (in) - llen - desc[ndescs-1].begin;
  429.  
  430.     rewind (in);
  431.  
  432.     qsort (node, nnodes, sizeof (struct node),
  433.         (int (*)(const void *,const void *))cmp_nodes);
  434.     qsort (cmd, ncmds, sizeof (struct cmd),
  435.         (int (*)(const void *,const void *))cmp_cmds);
  436.  
  437.     fputs (header, stdout);
  438.  
  439.     llen = 0;
  440.  
  441.     for (t=0; t<nnodes; t++)
  442.     {
  443.     i = strlen (node[t].title);
  444.  
  445.     if (i > llen)
  446.         llen = i;
  447.     }
  448.  
  449.     for (t=0; t<nnodes; t++)
  450.     fprintf (stdout, "    @{\" %*s \" LINK \"%s\"}\n", -llen, node[t].title, node[t].name);
  451.  
  452.     fprintf (stdout, "\n@ENDNODE \"MAIN\"\n\n");
  453.  
  454.     for (t=0; t<nnodes; t++)
  455.     {
  456.     fprintf (stdout, "@NODE \"%s\" \"%s\"\n", node[t].name, node[t].title);
  457.     fprintf (stdout, "@TOC \"MAIN\"\n\n");
  458.     fputs (node[t].body, stdout);
  459.  
  460.     nx=0;
  461.  
  462.     for (i=0; i<ncmds; i++)
  463.         if (isinlist (node[t].name, cmd[i].nodes))
  464.         cmdtable[nx++] = &cmd[i];
  465.  
  466.     if (nx)
  467.     {
  468.         qsort (cmdtable, nx, sizeof (struct cmd *),
  469.             (int (*)(const void *,const void *))cmp_cmdtable);
  470.  
  471.         for (i=0; i<nx; i++)
  472.         {
  473.         fmt_cmd (stdout, cmdtable[i]);
  474.         }
  475.     }
  476.     else
  477.         fprintf (stderr, "Unused nodes: %s\n", node[t].name);
  478.  
  479.     fprintf (stdout, "@ENDNODE \"%s\"\n\n", node[t].name);
  480.     }
  481.  
  482.     for (t=0; t<ndescs; t++)
  483.     {
  484.     sprintf (line, "desc%d", t);
  485.  
  486.     fprintf (stdout, "@NODE \"%s\" \"%s\"\n", line, desc[t].cmds);
  487.     fprintf (stdout, "@TOC \"MAIN\"\n\n");
  488.  
  489.     for (i=0; i<ncmds; i++)
  490.         if (isinlist (cmd[i].name, desc[t].cmds))
  491.         fprintf (stdout, "@{B}%s %s@{UB}\n", cmd[i].name, cmd[i].args);
  492.  
  493.     fseek (in, desc[t].begin, SEEK_SET);
  494.     for (i=desc[t].len; i>0; i-=j)
  495.     {
  496.         j = i < sizeof (puffer) ? i : sizeof (puffer);
  497.  
  498.         j = fread (puffer, 1, j, in);
  499.         if (j < 0) {
  500.         fprintf (stderr, "read error!\n", __LINE__);
  501.         exit (10);
  502.         }
  503.  
  504.         fwrite (puffer, 1, j, stdout);
  505.     }
  506.     /* fprintf (stdout, "insert %d bytes from %d\n", desc[t].len, desc[t].begin); */
  507.  
  508.     fprintf (stdout, "@ENDNODE \"%s\"\n\n", line);
  509.     }
  510.  
  511.     fprintf (stdout, "@NODE \"index\" \"Index\"\n");
  512.     fprintf (stdout, "@TOC \"MAIN\"\n\n");
  513.  
  514.     for (t=0; t<ncmds; t++)
  515.     fmt_cmd (stdout, &cmd[t]);
  516.  
  517.     fprintf (stdout, "@ENDNODE \"index\"\n\n");
  518.  
  519. } /* main */
  520.